home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1996 April: Mac OS SDK / Dev.CD Apr 96 SDK / Dev.CD Apr 96 SDK1.toast / Development Kits (Disc 1) / OpenDoc / Documentation / Tech Notes & Articles / Recipes / Imaging & Layout / Offscreen Canvases < prev    next >
Encoding:
Text File  |  1995-03-14  |  5.7 KB  |  80 lines  |  [TEXT/ttxt]

  1. OpenDoc™ Recipes
  2.  
  3.  
  4. Creating and Using Offscreen Canvases
  5. By The OpenDoc Design Team
  6. 19 April, 1994
  7.  
  8.  
  9. © 1993-1995  Apple Computer, Inc. All Rights Reserved.
  10. Apple, the Apple logo, and Macintosh are registered trademarks of Apple Computer, Inc.
  11. Mac and OpenDoc are trademarks of Apple Computer, Inc. 
  12.  
  13.  
  14. There are several situations where parts may want to create offscreen canvases. Two common cases are: double-buffering, and image manipulation. Embedded parts are likely to create offscreen canvases so they may double-buffer output for greater display efficiency and quality. Containing parts may place embedded parts on offscreen canvases so they can graphically manipulate the imaging output of the embedded part, and perhaps combine it with their own.
  15.  
  16. Creating an Offscreen Canvas
  17.  
  18. Creating the Canvas
  19.  
  20. To create a canvas, a part must first use a particular graphics system to create a platform canvas.  Then it can use the ODFacet::CreateCanvas() factory method to create an actual ODCanvas.
  21.  
  22. platformCanvas = MyCreatePlatformCanvas();    // as for your graphics system
  23. newCanvas = facet->CreateCanvas(ev,
  24.                         kGraphicsSystem,                                                                                    // enum code for your g.s.
  25.                         platformCanvas,
  26.                         kODTrue,                                                                                                                    // using a dynamic canvas
  27.                         kODTrue);                                                                                                                // this is OFFSCREEN
  28. newCanvas->SetOwner(ev, fSelf);                                                // fSelf is my PartWrapper
  29.  
  30. Putting the Canvas in a Facet
  31.  
  32. Containing Part
  33.  
  34. For a containing part to place an embedded part on an offscreen canvas, it must attach the canvas to the embedded facet. This must be done at facet creation time, before the embedded part gets noified of the new facet via FacetAdded(), where it may attempt to attach its own offscreen canvas (see below).
  35.  
  36. embeddedFacet = facet->CreateEmbeddedFacet(ev,
  37.                             frame, clipShape, externalTransform,
  38.                             newCanvas,                                                                // canvas created above
  39.                             kODNULL,                                                                        // no biasCanvas
  40.                             kODNULL, kODInFront);                    // frontmost facet
  41.  
  42. If an already-existing embedded facet has no canvas of its own, the containing part may add one. In that case, embedded parts will be notified automatically that their display canvas has changed.
  43.  
  44. facet->SetCanvas(ev, newCanvas);
  45.  
  46. Embedded Part
  47.  
  48. An embedded part may attach a canvas to one of its facets at any time. During FacetAdded() is a good time. The part may also choose to move the facet to an offscreen canvas later, for whatever reasons.
  49.  
  50. facet->SetCanvas(ev, newCanvas);
  51.  
  52. If the facet already has a canvas (which must have been assigned by the containing part), the embedded part may not attach a canvas to that facet. If it still wants to image on its own canvas, it must create a subframe of the facet’s frame, create a facet on that subframe, and attach the canvas to that facet.
  53.  
  54. Imaging on an Offscreen Canvas
  55.  
  56. If your part is written correctly, you shouldn’t have to do anything different to image on an offscreen canvas.  Some simple rules to follow:
  57.  
  58. •    Obtain the canvas to image on from the facet passed as a parameter to Part::Draw(). This may be an offscreen canvas. Using QuickDraw on the Macintosh, get a GrafPtr from the canvas, and SetPort() to display on it; follow similar actions for different graphics systems.
  59.  
  60. •    If a part needs to draw interactively (e.g. for rubber-banding or sweeping out a selection), it can image directly on the root facet’s canvas, which should be the same as the window’s display environment. All features of the canvas drawing environment computed by the facet are duplicated for the window environment: GetWindowFrameTransform, …ContentTransform, …AggregateClipShape. Use these values to image on the window environment.
  61.  
  62. •    If you perform any imaging on your facet’s canvas asynchronously (e.g. at idle time instead of in response to a ::Draw() call), you must call ODFacet::DrawnIn() to allow proper updating of offscreen canvas contents to onscreen. If a part’s facet is moved to an offscreen canvas while it is running, it will receive a ::CanvasChanged() call, which will allow it to tranfer its asynchronous imaging to the new canvas. 
  63.  
  64. •    Use the Invalidate() and Validate() calls in ODFrame and ODFacet to mark whether areas on a canvas need repainting. These will either call the corresponding calls in the underlying graphics toolbox, or accumulate the invalid area on an offscreen canvas. This way, invalidation is performed the same way for on- or offscreen canvases.
  65.  
  66. Updating an Offscreen Canvas
  67.  
  68. The part which owns an offscreen canvas is responsible for tranferring its contents to its parent canvas. This is because only the part which created the canvas can be assumed to know how to tranfer its contents. The parent and child canvases may have different formats (e.g. bitmap vs. display list), or the owner may want to transform the canvas contents as it copies them (e.g. rotate or tint).
  69.  
  70. When a containing part has placed an embedded facet on an offscreen canvas, it should force the embedded part to draw before the containing part itself draws any of its own contents. This ensures that the contents of the offscreen canvas are up to date, and can safely be combined with the containing part’s contents. In the containing part’s ::Draw() method:
  71.  
  72. embeddedFacet->Draw(ev, invalidShape);
  73. embeddedFacet->DrawChildren(ev, invalidShape); // in case it has embedded parts
  74. // draw some content...
  75. // ...
  76. offscreen = MyExtractBitmap(embeddedFacet->GetCanvas(ev));
  77. MyTransferBitmap(offscreen);
  78.  
  79. If embedded parts display asynchronously, the containing part which owns the canvas on which they image will be notified via the ::CanvasUpdated() call. The part may transfer the content from the offscreen canvas at this time, or it may choose to defer it until later, for reasons of efficiency or minimizing excessive redrawing.
  80.